package com.tenbent.product.base.security.impl;

//import com.tenbent.product.base.exception.TenbentException;
import com.tenbent.product.base.exception.TenbentException;
import com.tenbent.product.base.security.CustomFilterInvocationSecurityMetadataSource;
import com.tenbent.product.center.cache.PermCacheService;
//import com.tenbent.product.center.resource.bo.Resource;
//import com.tenbent.product.center.resource.service.ResourceService;
//import com.tenbent.product.center.role.bo.RoleResource;
//import com.tenbent.product.center.role.service.RoleResourceService;
//import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
//import org.springframework.cache.CacheManager;
import org.springframework.security.access.ConfigAttribute;
//import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.AntPathMatcher;

import java.util.*;

/**
 * 自定义获取url权限配置
 *
 * 这里以内存的map来展示一下，实际应用可以从分布式配置中心或者数据库中读取，另外循环遍历这个可能消耗性能，必要时得优化一下。
 *
 * @author Randy
 *
 *         Created by ThinkPad on 2017/9/7.
 */
public class CustomFilterInvocationSecurityMetadataSourceImpl implements CustomFilterInvocationSecurityMetadataSource {

	private Logger logger = LoggerFactory.getLogger(CustomFilterInvocationSecurityMetadataSourceImpl.class);

	private final AntPathMatcher antPathMatcher = new AntPathMatcher();

	/**
	 *
	 * 此处可以修改为从数据库获取资源权限
	 *
	 */
	// private final Map<String, Collection<ConfigAttribute>> urlRoleMap = new
	// HashMap<String, Collection<ConfigAttribute>>() {
	// {
	// ConfigAttribute role_user = new SecurityConfig("ROLE_USER");
	// ConfigAttribute role_admin = new SecurityConfig("ROLE_ADMIN");
	// ConfigAttribute role_dba = new SecurityConfig("ROLE_DBA");
	//
	// Collection<ConfigAttribute> collection_home = new ArrayList<>();
	// collection_home.add(role_user);
	// collection_home.add(role_admin);
	// collection_home.add(role_dba);
	//
	// Collection<ConfigAttribute> collection_hello = new ArrayList<>();
	// collection_hello.add(role_user);
	//
	// Collection<ConfigAttribute> collection_admin = new ArrayList<>();
	// collection_admin.add(role_admin);
	//
	// Collection<ConfigAttribute> collection_dba = new ArrayList<>();
	// collection_dba.add(role_dba);
	// collection_dba.add(role_admin);
	//
	// put("/eg/home/**", collection_home);
	// put("/eg/hello/**", collection_hello);
	// put("/eg/admin/**", collection_admin);
	// put("/eg/dba/**", collection_dba);
	// }
	// };

	// @Autowired
	// @Qualifier("roleResourceServiceImpl")
	// private RoleResourceService roleResourceService;
	//
	// @Autowired
	// @Qualifier("resourceServiceImpl")
	// private ResourceService resourceService;
	//
	// @Autowired
	// private CacheManager cacheManager;

	@Autowired
	@Qualifier("permCacheServiceImpl")
	private PermCacheService permCacheService;

	/**
	 * 获取URL资源的权限
	 *
	 * @param obj
	 *            请求url
	 */
	@Override
	public Collection<ConfigAttribute> getAttributes(Object obj) throws IllegalArgumentException {

		// object 是一个URL ,为用户请求URL
		FilterInvocation fi = (FilterInvocation) obj;
		String url = fi.getRequestUrl();
		// String httpMethod = fi.getRequest().getMethod();
		if ("/".equals(url)) {
			return null;
		}
		int firstQuestionMarkIndex = url.indexOf(".");
		// 判断请求是否带有参数 如果有参数就去掉后面的后缀和参数(/index.do --> /index)
		if (firstQuestionMarkIndex != -1) {
			url = url.substring(0, firstQuestionMarkIndex);
		}
		Map<String, Collection<ConfigAttribute>> urlRoleMap = getAllResoucePermestion();
		for (Map.Entry<String, Collection<ConfigAttribute>> entry : urlRoleMap.entrySet()) {
			if (antPathMatcher.match(entry.getKey(), url)) {
				return entry.getValue();
			}
		}
		// 没有匹配到的处理方式 (场景一 默认增加ROLE_USER，场景二 返回null 即放行没有权限要求)
		// return SecurityConfig.createList("ROLE_USER"); // 场景一
		return null; // 场景二
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return FilterInvocation.class.isAssignableFrom(clazz);
	}

	/**
	 * 获取所有资源对应的权限
	 *
	 * 改成数据库形式后期需要缓存优化
	 *
	 * 注意 同一个类中调用注解式缓存是不起作用的，因为AOP代理还没生成。
	 *
	 * 所以只能把逻辑些到另外的类中才能生效，也就是为什么要用CacheService
	 *
	 * 类下的方法代替此段逻辑，如果不想使用此方式，则只能手动在业务逻辑中硬
	 *
	 * 编码的方式例如：
	 *
	 * cacheManager.getCache("permCache").put("resourcePermestion", urlRoleMap);
	 * cacheManager.getCache("permCache").get("resourcePermestion", Map.class);
	 *
	 */
	@Override
	public Map<String, Collection<ConfigAttribute>> getAllResoucePermestion() {

		// Map<String, Collection<ConfigAttribute>> urlRoleMap =
		// cacheManager.getCache("permCache")
		// .get("resourcePermestion", Map.class);
		// if (null != urlRoleMap && !urlRoleMap.isEmpty()) {
		// return urlRoleMap;
		// }

		// urlRoleMap = new HashedMap();
		// List<Resource> resources = resourceService.getAll();
		// if (null == resources || resources.isEmpty()) {
		// throw new TenbentException(500, "资源不能为空！");
		// }
		// for (Resource resource : resources) {
		// RoleResource roleResource = new RoleResource();
		// roleResource.setResourceId(resource.getId());
		// List<RoleResource> roleResources =
		// roleResourceService.queryObj(roleResource);
		// if (null == roleResources || roleResources.isEmpty()) {
		// continue;
		// }
		// Collection<ConfigAttribute> configAttributes = new
		// ArrayList<>(roleResources.size());
		// for (RoleResource roleResource1 : roleResources) {
		// configAttributes.add(new
		// SecurityConfig(roleResource1.getRoleCode()));
		// }
		// urlRoleMap.put(resource.getUrl(), configAttributes);
		// }

		// cacheManager.getCache("permCache").put("resourcePermestion",
		// urlRoleMap);
		// return urlRoleMap;

		try {
			return permCacheService.getAllResoucePermestion();
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("获取资源(url)权限异常，原因： {}", e);
			throw new TenbentException(500, "the perm of resource(url) is error!");
		}

	}
}
